using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Mail;
using MacomberMap.Common.Database_Interface;
using System.Xml;
using System.Windows.Forms;
using System.Reflection;
using System.Data.Common;
using MacomberMap.Common.Data;

namespace MacomberMap.Common.Internals
{
    /// <summary>
    /// This class holds all information on the MM Loader
    /// </summary>
    public static class MM_Configuration
    {
        #region Variable declarations
        /// <summary>Our collection of databases to which we have stored credentials</summary>
        public static SortedDictionary<String, MM_Database> Databases = new SortedDictionary<string, MM_Database>();

        /// <summary>The default database</summary>
        public static MM_Database DefaultDatabase;

        /// <summary>Our collection of mail recipients to receive logs via email</summary>
        public static List<MailAddress> LogRecipients;

        /// <summary>The log sender from whom emails should originate</summary>
        public static MailAddress LogSender;

        /// <summary>The name of the SMTP server</summary>
        public static string SMTPServer;

        /// <summary>The time at which the Macomber Map Loader was started</summary>
        public static DateTime StartupTime;

        /// <summary>The initial hash element size for the CIM element array</summary>
        public static int InitialHashSize = 1000000;

        /// <summary>The loading factor for the CIM Element lookup hash table</summary>
        public static float HashLoadFactor=0.5f;

        /// <summary>Initial size for the list of CIM types</summary>
        public static int InitialTypeListSize = 100;

        /// <summary>File buffer size for indexing the CIM file</summary>
        public static int FileBufferSize=1024;

        /// <summary>The path to the shapeconverter</summary>
        public static string ShapeConverter;

        /// <summary>The master database for authentication purposes</summary>
        public static MM_Database MasterDatabase;

        /// <summary>The size of the socket buffer for TCP/IP communications</summary>
        public static int SocketBufferSize = 1024;
        
        /// <summary>The collection of data point definitions</summary>
        public static Dictionary<String, MM_Data_Source> DataSources = new Dictionary<string, MM_Data_Source>();

        /// <summary>The collection of data types</summary>
        public static Dictionary<String, MM_Data_Type> DataTypes = new Dictionary<string, MM_Data_Type>();

        /// <summary>The collection of data values</summary>
        public static Dictionary<String, MM_Data_Value> DataValues = new Dictionary<string, MM_Data_Value>();

        /// <summary>Maintain the XML file in memory for applications to read specific data</summary>
        public static XmlDocument xConfig;
        #endregion

        #region Initialization
        /// <summary>
        /// Open our XML Configuration file, and load all information in memory
        /// </summary>
        public static void LoadConfiguration()
        {            

            xConfig = new XmlDocument();
            xConfig.Load(Application.StartupPath + "\\MacomberMapConfiguration.xml");

            //Initialize our dictionaries
            LogRecipients = new List<MailAddress>(10);

            //Go through all of our elements, and load their results into the configuration
            foreach (XmlElement xElem in xConfig.DocumentElement.ChildNodes)
                if (xElem.Name == "Database")
                {
                    MM_Database NewDatabase = MM_Database.CreateDatabaseConnection(xElem);
                    Databases.Add(xElem.Attributes["Name"].Value, NewDatabase);                    
                }
                else if (xElem.Name == "LogRecipient" && xElem.HasAttribute("DisplayName"))
                    LogRecipients.Add(new MailAddress(xElem.Attributes["Email"].Value, xElem.Attributes["DisplayName"].Value));
                else if (xElem.Name == "LogRecipient")
                    LogRecipients.Add(new MailAddress(xElem.Attributes["Name"].Value));
                else if (xElem.Name == "LogSender")
                    LogSender = new MailAddress(xElem.Attributes["Email"].Value, xElem.Attributes["DisplayName"].Value);
                else if (xElem.HasAttribute("Value"))
                    SetValue(xElem.Name, xElem.Attributes["Value"].Value);
                else if (xElem.Name == "MacomberMap_DataPoints")
                    foreach (XmlElement xE in xElem.ChildNodes)
                    {
                        MM_Data_Source DataSource = new MM_Data_Source(xE);
                        DataSources.Add(xE.Attributes["Name"].Value, DataSource);
                        foreach (MM_Data_Type DataType in DataSource.DataType)
                        {
                            DataTypes.Add(DataSource.Name + "\\" + DataType.Name, DataType);
                            foreach (MM_Data_Value DataValue in DataType.DataValues)
                                DataValues.Add(DataSource.Name + "\\" + DataType.Name + "\\" + DataValue.Name, DataValue);
                        }
                    }
            //Now, mark all of our lists as complete
            LogRecipients.TrimExcess();

           
           
            StartupTime = DateTime.Now;
        }
        #endregion

        private static void SetValue(String AttributeName, String AttributeValue)
        {
            FieldInfo OutInfo = typeof(MM_Configuration).GetField(AttributeName);
            if (OutInfo.FieldType == typeof(string))
                OutInfo.SetValue(typeof(MM_Configuration), AttributeValue);
            else if (OutInfo.FieldType == typeof(int))
                OutInfo.SetValue(typeof(MM_Configuration), XmlConvert.ToInt32(AttributeValue));
            else if (OutInfo.FieldType == typeof(float))
                OutInfo.SetValue(typeof(MM_Configuration), XmlConvert.ToSingle(AttributeValue));
        }

        /// <summary>
        /// Save our configuration to the XML file
        /// </summary>
        public static void SaveConfiguration()
        {
            //Create our outgoing configuration file
            using (XmlTextWriter xW = new XmlTextWriter("MacomberMapLoaderConfiguration.xml", Encoding.UTF8))
            {
                xW.WriteStartDocument(true);

                xW.WriteStartElement("MacomberMap_Loader");
                //Write our databases
                foreach (MM_Database Db in Databases.Values)
                    Db.SaveConfigurationParameters(xW);

                //Write our email recipients
                foreach (MailAddress Address in LogRecipients)
                {
                    xW.WriteStartElement("LogRecipient");
                    xW.WriteAttributeString("Email", Address.Address);
                    if (!String.IsNullOrEmpty(Address.DisplayName))
                        xW.WriteAttributeString("DisplayName", Address.DisplayName);
                    xW.WriteEndElement();
                }

                //Write our email sender
                xW.WriteStartElement("LogSender");
                xW.WriteAttributeString("Email", LogSender.Address);
                xW.WriteAttributeString("DisplayName", LogSender.DisplayName);
                xW.WriteEndElement();

                //Write out the rest of our attributes
                foreach (FieldInfo fI in typeof(MM_Configuration).GetType().GetFields(BindingFlags.Static))
                    if (fI.FieldType == typeof(int) || fI.FieldType == typeof(float) || fI.FieldType == typeof(string))
                    {
                        xW.WriteStartElement(fI.Name);
                        xW.WriteAttributeString("Value", fI.GetValue(typeof(MM_Configuration)).ToString());
                        xW.WriteAttributeString("Type", fI.FieldType.Name);
                        xW.WriteEndElement();
                    }

                xW.Flush();
                xW.Close();
            }
        }
    }
}
